<template>
  <div ref="mapRef">
    <n-spin :show="loading" class="spin"></n-spin>
  </div>
</template>

<script setup>
  import AMapLoader from '@amap/amap-jsapi-loader'
  import setting from '@/settings/projectSetting'
  import { ref, watch, onMounted } from 'vue'

  const emit = defineEmits(['update:modelValue'])
  const props = defineProps({
    modelValue: {
      type: Object,
      default() {
        return {}
      },
    },
    setMode: {
      type: Boolean,
      default: false,
    },
  })

  // 地点
  const location = computed({
    get() {
      return props.modelValue
    },
    set(val) {
      emit('update:modelValue', val)
    },
  })

  watch(location, (val) => {
    if (val.longitude && val.latitude) {
      if (amap) {
        drawMarker()
      }
    }
  })

  // 方法实例
  let amap, geocoder, marker, placeSearch
  const map = shallowRef(null)
  const mapRef = ref()
  const mapConfig = {
    center: [119.293961, 26.061637],
    resizeEnable: true,
    zoom: 11,
  }
  const loading = ref(false)

  onMounted(() => {
    initAmap()
  })
  const initAmap = () => {
    loading.value = true
    AMapLoader.load({
      key: setting.amapKey, // key
      version: '2.0',
      Loca: {
        // 是否加载 Loca， 缺省不加载
        version: '2.0.0', // Loca 版本，缺省 1.3.2
      },
    }).then((AMap) => {
      loading.value = false
      amap = AMap
      //设置地图容器id
      map.value = new AMap.Map(mapRef.value, mapConfig)

      // 添加插件
      AMap.plugin(
        [
          'AMap.Geolocation',
          'AMap.Autocomplete',
          'AMap.PlaceSearch',
          'AMap.Scale',
          'AMap.OverView',
          'AMap.ToolBar',
          'AMap.MapType',
          'AMap.PolyEditor',
          'AMap.CircleEditor',
          'AMap.Geocoder',
        ],
        () => {
          //异步同时加载多个插件
          // 缩放条
          const toolbar = new AMap.ToolBar()
          // 比例尺
          const scale = new AMap.Scale()

          //加载地理编码插件
          geocoder = new AMap.Geocoder({
            radius: 1000, //以已知坐标为中心点，radius为半径，返回范围内兴趣点和道路信息
            extensions: 'all', //返回地址描述以及附近兴趣点和道路信息，默认“base”
          })

          placeSearch = new AMap.PlaceSearch({
            map: map.value,
            city: '',
            pageSize: 30, // 单页显示结果条数
            pageIndex: 1, // 页码
            citylimit: false, // 是否强制限制在设置的城市内搜索
            autoFitView: true,
          })

          // 定位
          const geolocation = new AMap.Geolocation({
            enableHighAccuracy: true, //是否使用高精度定位，默认:true
            timeout: 10000, //超过10秒后停止定位，默认：5s
            position: 'RT', //定位按钮的停靠位置
            buttonOffset: new AMap.Pixel(10, 20), //定位按钮与设置的停靠位置的偏移量，默认：Pixel(10, 20)
            zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
          })

          map.value.addControl(geolocation)
          map.value.addControl(toolbar)
          map.value.addControl(scale)
        },
      )

      // 添加点击事件
      if (props.setMode) {
        map.value.on('click', onMapClick)
      }
      // 有值就描点标记
      if (location.value.longitude) {
        drawMarker()
      }
    })
  }

  // 点击地图事件
  function onMapClick(e) {
    const { lng, lat } = e.lnglat
    // 逆地理编码
    geocoder.getAddress([lng, lat], (status, result) => {
      if (status === 'complete' && result.info === 'OK') {
        const { addressComponent, formattedAddress } = result.regeocode
        let { city, province, district } = addressComponent
        if (!city) {
          // 直辖市
          city = province
        }
        location.value = {
          longitude: lng,
          latitude: lat,
          address: formattedAddress,
          zone: [province, city, district],
        }
      }
    })
  }

  // 绘制地点marker
  function drawMarker(val) {
    const { longitude, latitude, address } = location.value || val
    if (marker) {
      marker.setMap(null)
    }

    const icon = new amap.Icon({
      size: new amap.Size(26, 32), // 图标尺寸
      image: new URL(`/img/AMap/bjzx_icon_dw@2x.png`, import.meta.url).href, // Icon的图像
      imageSize: new amap.Size(26, 32), // 根据所设置的大小拉伸或压缩图片
    })

    marker = new amap.Marker({
      position: new amap.LngLat(longitude, latitude),
      anchor: 'bottom-center',
      icon: icon,
    })

    // 如果有地址
    if (address) {
      marker.setLabel({
        content: '<span>' + address + '</span>', //设置文本标注内容
        direction: 'bottom', //设置文本标注方位
        offset: new amap.Pixel(0, 2), //设置文本标注偏移量
      })
    }

    map.value.add(marker)
    map.value.setZoomAndCenter(16, [longitude, latitude])
  }

  // 搜索地图
  function handleSearch(queryString, cb) {
    placeSearch.search(queryString, (status, result) => {
      if (result && typeof result === 'object' && result.poiList) {
        const list = result.poiList.pois
        list.forEach((item) => {
          item.value = item.name
          item.label = item.name
        })
        cb(list)
      } else {
        cb([])
      }
    })
  }

  // 点击搜索项
  function handleSelect(item) {
    const { pname, cityname, adname, address, name } = item
    const { lng, lat } = item.location
    location.value = {
      longitude: lng,
      latitude: lat,
      address,
      zone: [pname, cityname, adname],
      name,
    }
    map.value.setZoomAndCenter(16, [lng, lat])
  }

  defineExpose({
    handleSearch,
    handleSelect,
  })
</script>

<style lang="scss" scoped>
  .spin {
    width: 100%;
    height: 100%;
  }
</style>
